#include <QDebug>
#include <QPainter>
#include <QPaintEvent>
#include <QFontMetrics>
#include "HistogramWidget.h"

HistogramWidget::HistogramWidget(QWidget *parent) :
	QWidget(parent), m_iValueMin(0), m_iValueMax(0), m_iRangeMin(0), m_iRangeMax(0),
	m_ptMouse(-1, -1)
{
	this->setMouseTracking(true);
}

void HistogramWidget::SlotSetHistogramData(const QMap<int, int> &data)
{
	m_data = QMap<int, int>(data);
	this->calcMinMax();
	this->update();
}

void HistogramWidget::paintEvent(QPaintEvent *event)
{
	Q_UNUSED(event);

	QPainter painter(this);
	QRect rect(this->rect());

	painter.fillRect(rect, Qt::transparent);

	QFontMetrics fm(painter.font());
	QString strMin(QString::number(m_iRangeMin));
	QString strMax(QString::number(m_iRangeMax));
	QRect rectMin(fm.boundingRect(strMin));
	QRect rectMax(fm.boundingRect(strMax));

	rectMin.adjust(-1, -1, 1, 1);
	rectMax.adjust(-1, -1, 1, 1);

	int height = qMax(rectMin.height(), rectMax.height());
	QRect rectGraph(rect.adjusted(2, 2, -2, -height));
	this->drawHistogram(painter, rectGraph);
	rectMin.moveTopLeft(rectGraph.bottomLeft());
	rectMax.moveTopRight(rectGraph.bottomRight());
	painter.drawText(rectMin, strMin);
	painter.drawText(rectMax, strMax);
	painter.drawRect(rectGraph);
}

void HistogramWidget::mouseMoveEvent(QMouseEvent *event)
{
	m_ptMouse = event->pos();
	this->update();
}

void HistogramWidget::leaveEvent(QEvent *event)
{
	m_ptMouse.setX(-1);
	m_ptMouse.setY(-1);
	this->update();
}

void HistogramWidget::calcMinMax()
{
	m_iRangeMax = 16383;
	m_iRangeMin = 0;

	if(m_data.isEmpty())
	{
		m_iValueMax = 0;
		m_iValueMin = 0;
	}
	else
	{
		QList<int> values = m_data.values();

		qSort(values);
		m_iValueMax = values.last();
		m_iValueMin = values.first();
	}
}

void HistogramWidget::drawHistogram(QPainter &painter, QRectF rect)
{
	float lineWidth(1.f);
	QVector<QLineF> lines;

	if(m_iRangeMax > 0)
	{
		float height = rect.height();

		lineWidth = 1.f * rect.width() / m_iRangeMax;

		for (int var = m_iRangeMin; var < m_iRangeMax; ++var)
		{
			int iValue = m_data.value(var);

			if(iValue == 0) continue;

			float xPos = (var + 1) * lineWidth;
			float yPos = 1.f * iValue / m_iValueMax * height;
			const QPointF ptBase(rect.topLeft());

			lines << QLineF(QPointF(xPos + ptBase.x(), height - yPos + ptBase.y()), QPointF(xPos + ptBase.x(), height + ptBase.y()));
		}
	}

	painter.save();
	painter.setPen(QPen(Qt::red, lineWidth));
	painter.drawLines(lines);
	painter.restore();

	if(rect.contains(m_ptMouse))
	{
		painter.save();
		painter.setPen(Qt::darkGray);
		painter.drawLine(m_ptMouse.x(), rect.top(), m_ptMouse.x(), rect.bottom());
		painter.restore();

		QFontMetrics fm(painter.font());
		QString strVal(QString::number((int)((m_ptMouse.x() - rect.left()) / lineWidth)));
		QRect rectStr(fm.boundingRect(strVal));

		rectStr.adjust(-1, -1, 1, 1);

		if((rect.right() - m_ptMouse.x()) > rectStr.width())
		{
			rectStr.moveTopLeft(QPoint(m_ptMouse.x(), rect.top()));
		}
		else
		{
			rectStr.moveTopRight(QPoint(m_ptMouse.x(), rect.top()));
		}

		painter.drawText(rectStr, strVal);
	}
}
